package me.spring.cloud.components.starter.version.core;

import me.spring.cloud.common.components.util.lang.StringUtil;
import me.spring.cloud.components.starter.version.anntoation.ApiVersion;
import me.spring.cloud.components.starter.version.anntoation.ClientVersion;
import me.spring.cloud.components.starter.version.condition.ClientVersionRequestCondition;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

/**
 * @author luffy
 * @date 2019-04-18 14:18
 */
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

  /**
   * @return org.springframework.web.servlet.mvc.method.RequestMappingInfo
   * @Author luffy
   * @Description 重写此处，保证读取我们的注解apiversion
   * @Date 2019-04-18 14:27
   * @Param [method, handlerType]
   **/
  @Override
  protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
    RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);
    if (mappingInfo != null) {
      RequestMappingInfo apiVersionMappingInfo = getApiVersionMappingInfo(method, handlerType);
      return apiVersionMappingInfo == null ? mappingInfo : apiVersionMappingInfo.combine(mappingInfo);
    }
    return mappingInfo;
  }

  @Override
  protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
    ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ClientVersion.class);
    return createRequestCondtion(clientVersion);
  }

  /**
   * @return org.springframework.web.servlet.mvc.condition.RequestCondition<?>
   * @Author luffy
   * @Description 重新定义clientversion的条件匹配 ø   * @Param [method]
   **/
  @Override
  protected RequestCondition<?> getCustomMethodCondition(Method method) {
    ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(method, ClientVersion.class);
    return createRequestCondtion(clientVersion);
  }

  private RequestCondition<?> createRequestCondtion(ClientVersion clientVersion) {
    if (clientVersion == null) {
      return null;
    }
    if (clientVersion.value() != null && clientVersion.value().length > 0) {
      return new ClientVersionRequestCondition(clientVersion.value());
    }
    if (clientVersion.expression() != null && clientVersion.expression().length > 0) {
      return new ClientVersionRequestCondition(clientVersion.expression());
    }
    return null;
  }

  private RequestMappingInfo getApiVersionMappingInfo(Method method, Class<?> handlerType) {
    //优先查找method
    ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class);
    if (apiVersion == null || StringUtil.isBlank(apiVersion.value())) {
      apiVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ApiVersion.class);
    }
    return apiVersion == null || StringUtil.isBlank(apiVersion.value()) ? null : RequestMappingInfo
        .paths(apiVersion.value())
        .build();
  }
}
